#pragma once
#include "stdafx.h"
#include <vector>
template <typename T>
class Vector
{
public:
	typedef typename vector<T>::value_type value_type;
	typedef typename vector<T>::iterator iterator;
	typedef typename vector<T>::reverse_iterator reverse_iterator;
	typedef typename vector<T>::const_iterator const_iterator;
	typedef typename vector<T>::const_reference const_reference;
	typedef typename vector<T>::reference reference;
	typedef typename vector<T>::size_type size_type;
	
	template<typename T>
	struct remove_pointer
	{
	    typedef T type;
	};
	
	template<typename T>
	struct remove_pointer<T*>
	{
	    typedef T type;
	};

	typedef typename remove_pointer<T>::type type;

	Vector()
		:m_data()
	{
	}

	Vector(const Vector<T>& o)
	{
		Constructor(o,boost::is_pointer<T>());
	}
	
	~Vector()
	{
		Destroy(boost::is_pointer<T>());
	}

	void Constructor(const Vector<T>& o, const boost::false_type&)
	{
		m_data(o);
	}

	void Constructor(const Vector<T>& o, const boost::true_type&)
	{
		for(const_iterator iter=o.begin();iter!=o.end();iter++)
		{
			m_data.push_back(new type(**iter));
		}
	}
	
	void Destroy(const boost::false_type&)
	{
		m_data.clear();
	}
	
	void Destroy(const boost::true_type&)
	{
		for(iterator iter=begin();iter!=end();iter++)
		{
			delete *iter;
		}
		m_data.clear();
	}

	iterator begin()
	{
		return m_data.begin();
	}
	
	iterator end()
	{
		return m_data.end();
	}
	
	reverse_iterator rbegin()
	{
		return m_data.rbegin();
	}
	
	reverse_iterator rend()
	{
		return m_data.rend();
	}
	
	const_iterator begin() const
	{
		return m_data.begin();
	}
	
	const_iterator end() const
	{
		return m_data.end();
	}
	
	void reserve(size_type _Count)
	{
		return m_data.reserve(_Count);
	}
	
	size_type capacity() const
	{	
		return m_data.capacity();
	}
	
	void resize(size_type _Newsize)
	{	// determine new length, padding with _Ty() elements as needed
		m_data.resize(_Newsize);
	}
	
	size_type size() const
	{
		return m_data.size();
	}

	size_type max_size() const
	{
		return m_data.max_size();
	}
	
	const_reference at(size_type _Pos) const
	{	
		return m_data.at(_Pos);
	}

	reference at(size_type _Pos)
	{
		return m_data.at(_Pos);
	}
		
	const_reference operator[](size_type _Pos) const
	{	
		return m_data[_Pos];
	}

	reference operator[](size_type _Pos)
	{
		return m_data[_Pos];
	}
		
		
	void push_back(const T& _Val)
	{
		m_data.push_back(_Val);
	}

	void pop_back()
	{
		m_data.pop_back();
	}

	bool empty() const
	{	// test if sequence is empty
		return (m_data.size() == 0);
	}

	void clear()
	{
		Destroy(boost::is_pointer<T>());
	}

	void Copy(const Vector<T>& old,const boost::true_type&)
	{
		m_data.clear();
		for(const_iterator iter=old.begin();iter!=old.end();iter++)
		{
			m_data.push_back(new type(**iter));
		}

	}

	void Copy(const Vector<T>& old,const boost::false_type&)
	{
		m_data=old.m_data;
	}

	Vector<T>& operator=(const Vector<T>& right)
	{
		if(this!=&right)
		{
			Copy(right,boost::is_pointer<T>());
		}
		return *this;
	}
	
private:
	vector<T> m_data;
};